#pragma once

#include <stdint.h>
#include "gdbIO.h"
#include "gdbPacket.h"
#include <target/target.h>

/* 
  gdb remote debug protocl 
*/

class gdbRDP
{
public:
    gdbRDP();
    ~gdbRDP();

    int loop(gdbIORemote &rio, targetIO &tio, gdbPacket &pkt);
    void setLogger(void *ctx, void (*out)(void* ctx, const char *fmt, ...));

private:
    int cmd_q(gdbPacket &pkt);
    int qSupported(gdbPacket &pkt);
    bool qTStatus(gdbPacket &pkt);
    bool qXfer(gdbPacket &pkt);
    bool qfThreadInfo(gdbPacket &pkt);
    bool qsThreadInfo(gdbPacket &pkt);
    bool qAttached(gdbPacket &pkt);
    bool qC(gdbPacket &pkt);
    bool qOffsets(gdbPacket &pkt);
    bool qSymbol(gdbPacket &pkt);

    int cmd_v(targetIO &tio, gdbPacket &pkt);
    bool vCont(targetIO &tio, gdbPacket &pkt);

    bool cmd_H(gdbPacket &pkt);
    bool cmd_g(targetIO &tio, gdbPacket &pkt);
    bool cmd_p(targetIO &tio, gdbPacket &pkt);
    bool cmd_P(targetIO &tio, gdbPacket &pkt);
    bool cmd_m(targetIO &tio, gdbPacket &pkt);
    bool cmd_Z(targetIO &tio, gdbPacket &pkt);
    bool cmd_z(targetIO &tio, gdbPacket &pkt);
    bool cmd_c(targetIO &tio, gdbPacket &pkt);
    bool cmd_D(targetIO &tio, gdbPacket &pkt);
    bool cmd_T(targetIO &tio, gdbPacket &pkt);
    bool cmd_s(targetIO &tio, gdbPacket &pkt);
    bool cmd_QMark(targetIO &tio, gdbPacket &pkt);

    bool cmd_CTRL_C(targetIO &tio, gdbPacket &pkt); //0x03

private:
    int readPacket(gdbIORemote &rio, gdbPacket &pkt);
    int writePacket(gdbIORemote &rio, gdbPacket &pkt);
    int command(targetIO &tio, gdbPacket &pkt);
    void sendAck(gdbIORemote &rio, char c);
    void pollTargetStatus(gdbIORemote &rio, targetIO &tio, gdbPacket &pkt);

private:
    void *lctx;
    void (*lout)(void* ctx, const char *fmt, ...);
    bool ctrl_c;
};
